/*
 * @Author: Jiraiya
 * @Date: 2020-02-29 22:44:55
 * @LastEditors: Jiraiya
 * @LastEditTime: 2020-03-02 17:12:31
 * @Description: 
 */
 
 // length返回参数个数，默认不算

 const fun1 = (a, b)=>{}
 const fun2 = (a, b = 1) => {}
 console.log(fun1.length, fun2.length) // 2 1

 // 函数体在哪里调用就从该作用域开始
 const l = console.log
 const a = 'outer'
 const b = () => a
 function f(){
     const a = 'inner'
     console.log(b())
 }

 function ff(fx = b){
     const a = 'inner'
     console.log(fx())
 }
 f() // 'outer'
 ff() // 'outer'


// 三个作用域 全局 参数 函数体
var x = 1
function foo(x, y = function(){ x = 2}){
    var x = 3;
    y();
    console.log(x);
}
foo() // 3
console.log(x) // 1

// 同上
var x = 1
function foo(x, y = function(){ x = 2}){
    x = 3
    y()
    console.log(x)
}

foo() // 2
console.log(x) // 1

// name属性
const f1 = function (){}
console.log(f1.name)// f1

const f2 = function ff2(){}
console.log(f2.name) // ff2

console.log((new Function()).name) // anonymous

function f3(){}
console.log(f3.bind({}).name) // bound f3

console.log((function (){}).bind({}).name) // bound


// 箭头函数几个特点
var x = 1
const obj = {
    x: 2,
    f: ()=>{console.log(this === window)}
}
obj.f()

//🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏

// 递归的尾调优化

function fx(){
    // "use strict" 严格模式下面属性不生效
    console.log(arguments) //参数
    console.log(fx.caller) //调用该函数的函数
    console.log(arguments.callee) //函数本身
}
fx()

function factorial(n){
    if (n === 1) return 1;
    return n * factorial(n - 1);
}
console.log(factorial(5)) // 120

function factorial_tail(n, total = 1){
    "use strict"
    if(n === 1){ return total }
    return factorial_tail(n - 1, total = total * n)
}
console.log(factorial_tail(5)) // 120


function sum(n){
    if(n === 1){ return 1}
    return n + sum(n - 1)
}
console.log(sum(100000)) //栈溢出

"use strict"
function sum_tail(n, total = 1){
    if(n === 1){ return total }
    return sum_tail(n - 1, total += n)
}
console.log(sum_tail(100000))

// 1 1 2 3
function fibonacci(n){ 
    if(n <= 2) return 1;
    return fibonacci(n - 1) + fibonacci(n - 2)
}
console.log(fibonacci(10))

function fibonacci_tail(n, ac1 = 1, ac2 = 1){
    if(n <= 2) return ac2;
    return fibonacci_tail(n-1, ac2, ac1 + ac2)
}
console.log(fibonacci_tail(10))

//🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏🙏

// try...catch的catch可以省略参数
try{
    a
}catch{
    console.log('可以省略参数')
}